package com.ds.app.database;

import com.ds.app.AppCacheManager;
import com.ds.app.ModuleNotFoundException;
import com.ds.common.cache.CacheSizes;
import com.ds.common.cache.Cacheable;
import com.ds.common.database.DBAgent;
import com.ds.common.database.DBBeanBase;
import com.ds.common.logging.Log;
import com.ds.common.logging.LogFactory;
import com.ds.org.OrgManager;
import com.ds.org.Person;
import com.ds.org.PersonNotFoundException;
import com.ds.org.conf.OrgConfig;
import com.ds.org.conf.OrgConstants;
import com.ds.org.conf.Query;
import com.ds.org.conf.Query.ColumnMapping;
import com.ds.org.conf.Query.SqlClause;
import com.ds.server.OrgManagerFactory;
import com.ds.server.eumus.ConfigCode;

import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;


public class DbModuleProperty implements Cacheable, Serializable {

    protected static Log log =
            LogFactory.getLog(OrgConstants.CONFIG_KEY.getType(),
                    DbModuleProperty.class);
    public static final String DELETE = "DELETE", UPDATE = "UPDATE", NORMAL = "NORMAL", PUBLIC = "public";
    private String status = NORMAL;
    private String ID;

    private String moduleId;

    private String personId;

    private Integer x;

    private Integer y;

    private Integer width;

    private Integer height;

    //桌面图标位置{x:200,y:200}
    private String desktopLocation;

    private ConfigCode configCode;
    private boolean isPublic = false;


    private OrgConfig getConfig() {
        OrgConfig config = OrgConfig.getInstance(this.configCode);
        return config;
    }

    public DbModuleProperty(ConfigCode configCode) {
        if (configCode == null) {
            configCode = OrgConstants.CONFIG_KEY;
        }

        this.configCode = configCode;
    }

    public DbModuleProperty(String moduleId, ConfigCode configCode, String personId) throws ModuleNotFoundException {
        if (moduleId == null || moduleId.equals("")) {
            throw new ModuleNotFoundException();
        }
        this.moduleId = moduleId;

        if (personId == null) {
            personId = PUBLIC;
        }
        this.personId = personId;
        this.isPublic = true;
        this.configCode = configCode;
        loadFromDb();
    }

    public DbModuleProperty(String ID, ConfigCode configCode) throws ModuleNotFoundException {
        if (ID == null || ID.equals("")) {
            throw new ModuleNotFoundException();
        }
        this.ID = ID;
        if (configCode == null) {
            configCode = OrgConstants.CONFIG_KEY;
        }

        this.configCode = configCode;
        loadFromDb();
    }

    private void loadFromDb() throws ModuleNotFoundException {
        DBAgent db = null;
        try {
            db = new DBAgent(this.configCode.getType());

            loadBasic(db);
        } catch (Exception e) {

            if (ID != null) {
                log.error("ModuleProperty ID[" + ID + "] not found.");
                //throw new ModuleNotFoundException("ModuleProperty ID[" + ID + "] not found.");
            } else {
                log.error("ModuleProperty  moduleId[" + ID + "] not found.");
                //throw new ModuleNotFoundException("ModuleProperty  moduleId[" + ID + "] not found.");
            }

        } finally {
            if (db != null) {
                db.close();
            }
        }

    }

    public void update() {
        OrgManager cacheManager = OrgManagerFactory.getOrgManager();
        Person person = null;
        try {
            person = cacheManager.getPersonByID(this.personId);
        } catch (PersonNotFoundException e) {
            e.printStackTrace();
        }


        AppCacheManager.getInstance(configCode).getModulePrivateProcertyCache().put(ID, this);
        //	person.addModuleProperty(this.ID);
        this.status = UPDATE;
    }


    public void commit(Connection c) throws PersonNotFoundException {
        if (status.equals(NORMAL)) {
            return;
        }
        Connection innerc = null;
        if (c == null) {
            DBBeanBase db = new DBBeanBase(this.configCode.getType());
            innerc = db.getConn();
        } else {
            innerc = c;
        }


//		if (!person.getModulePropertyIdList().contains(this.ID)){
//			person.getModulePropertyIdList().add(this.ID);
//		}

        try {
            innerc.setAutoCommit(false);
            this.deleteModuleProperty(innerc);
            if (!status.equals(DELETE)) {
                this.insertModuleProperty(innerc);
            }
            if (c == null) {
                innerc.commit();
                innerc.close();
            }

            this.status = this.NORMAL;
        } catch (SQLException e) {
            e.printStackTrace();
            try {
                innerc.rollback();
                innerc.close();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
        }
    }


    private void loadBasic(DBAgent db) throws Exception {

        ResultSet rs = null;
        Query query = null;
        SqlClause sqlClause = null;
        Map columnMap = null;
        String strSql = null;

//		 1.基本信息
        query = getConfig().getQuery("ModuleProperty");
        if (query == null) {
            log.error("The ModuleProperty-query-sql is null, please specify it!");
            throw new ModuleNotFoundException();
        }
        sqlClause = query.getSqlClause("basic");
        if (sqlClause == null) {
            log.error("The ModuleProperty-query-sql is null, please specify it!");
            throw new ModuleNotFoundException();
        }
        columnMap = sqlClause.getColumnMappings();
        if (this.isPublic) {
            strSql = this.buildModuleIdSql(sqlClause);
        } else {
            strSql = buildSql(sqlClause);
        }


        if (db.execute(strSql) == 1) {
            rs = db.getQueryResult();
            if (!rs.next()) {
                throw new ModuleNotFoundException("ModuleProperty " + ID + " not found.");
            }
            ID =
                    getString(rs, columnMap.get("ID"));
            moduleId =
                    getString(rs, columnMap.get("moduleId"));

            if (columnMap.get("desktopLocation") != null && !columnMap.get("desktopLocation").equals("")) {
                desktopLocation =
                        getString(rs, columnMap.get("desktopLocation"));
            }
            personId =
                    getString(rs, columnMap.get("personId"));
            height =
                    getInt(rs, columnMap.get("height"));
            width =
                    getInt(rs, columnMap.get("width"));
            x =
                    getInt(rs, columnMap.get("x"));
            y =
                    getInt(rs, columnMap.get("y"));
        } else {
            throw new ModuleNotFoundException("ModuleProperty " + ID + " not found.");
        }
    }

    public int getCachedSize() {
        int size = 0;
        size += CacheSizes.sizeOfString(ID);
        size += CacheSizes.sizeOfString(moduleId);
        size += CacheSizes.sizeOfString(personId);
        size += CacheSizes.sizeOfObject(x);
        size += CacheSizes.sizeOfObject(y);
        size += CacheSizes.sizeOfObject(width);
        size += CacheSizes.sizeOfObject(height);
        return size;
    }


    public String getModuleId() {
        return moduleId;
    }

    public void setModuleId(String moduleId) {
        this.moduleId = moduleId;
    }

    public String getPersonId() {
        return personId;
    }

    public void setPersonId(String personId) {
        this.personId = personId;
    }


    public Integer getHeight() {
        return height;
    }

    public void setHeight(Integer height) {
        this.height = height;
    }

    public Integer getWidth() {
        return width;
    }

    public void setWidth(Integer width) {
        this.width = width;
    }

    public Integer getX() {
        return x;
    }

    public void setX(Integer x) {
        this.x = x;
    }

    public Integer getY() {
        return y;
    }

    public void setY(Integer y) {
        this.y = y;
    }

    private String buildSql(SqlClause sqlClause) {
        Map columnMap = sqlClause.getColumnMappings();
        String strSql = sqlClause.getMainClause();
        String strWhere = sqlClause.getWhereClause();
        if (strWhere != null && !strWhere.equals("")) {
            strSql = strSql + " " + strWhere + " AND "
                    + ((ColumnMapping) columnMap.get("ID")).getColumn()
                    + "='" + ID + "'";
        } else {
            strSql = strSql + " WHERE "
                    + ((ColumnMapping) columnMap.get("ID")).getColumn()
                    + "='" + ID + "'";
        }
        return strSql;
    }

    private String buildModuleIdSql(SqlClause sqlClause) {
        Map columnMap = sqlClause.getColumnMappings();
        String strSql = sqlClause.getMainClause();
        String strWhere = sqlClause.getWhereClause();
        if (strWhere != null && !strWhere.equals("")) {
            strSql = strSql + " " + strWhere + " AND "
                    + ((ColumnMapping) columnMap.get("moduleId")).getColumn()
                    + "='" + moduleId + "' AND " + columnMap.get("personId") + "='" + this.personId + "'";
        } else {
            strSql = strSql + " WHERE "
                    + ((ColumnMapping) columnMap.get("moduleId")).getColumn()
                    + "='" + moduleId + "' AND " + columnMap.get("personId") + "='" + this.personId + "'";
        }
        return strSql;
    }

    public String getID() {
        return ID;
    }

    public void setID(String id) {
        ID = id;
    }

    public void deleteModuleProperty(Connection c) throws SQLException {
        Query query = getConfig().getQuery("ModuleProperty");
        SqlClause sqlClause = query.getSqlClause("basic");
        Map columnMap = sqlClause.getColumnMappings();
        PreparedStatement ps = null;
        StringBuffer _sql = new StringBuffer(sqlClause.getDeleteClause() + " where ");
        _sql.append(columnMap.get("ID")).append("='" + this.ID + "'");
        ps = c.prepareStatement(_sql.toString());
        int deletCount = ps.executeUpdate();
        ps.close();

        AppCacheManager cacheManager = AppCacheManager.getInstance(configCode);
        cacheManager.getModulePrivateProcertyCache().remove(ID);
    }

    public void insertModuleProperty(Connection c) throws SQLException {
        Query query = getConfig().getQuery("ModuleProperty");
        SqlClause sqlClause = query.getSqlClause("basic");
        Map columnMap = sqlClause.getColumnMappings();
        StringBuffer _sql = new StringBuffer(sqlClause.getInsertClause() + "(");
        int _dirtyCount = 0;
        _sql.append(columnMap.get("ID")).append(",");
        _dirtyCount++;
        _sql.append(columnMap.get("moduleId")).append(",");
        _dirtyCount++;
        if (columnMap.get("desktopLocation") != null && !columnMap.get("desktopLocation").equals("")) {
            _sql.append(columnMap.get("desktopLocation")).append(",");
            _dirtyCount++;
        }
        _sql.append(columnMap.get("personId")).append(",");
        _dirtyCount++;
        _sql.append(columnMap.get("height")).append(",");
        _dirtyCount++;
        _sql.append(columnMap.get("width")).append(",");

        _dirtyCount++;
        _sql.append(columnMap.get("x")).append(",");
        _dirtyCount++;
        _sql.append(columnMap.get("y")).append(",");
        _dirtyCount++;
        _sql.setLength(_sql.length() - 1);
        _sql.append(") values (");
        for (int i = 0; i < _dirtyCount; i++)
            _sql.append("?,");
        _sql.setLength(_sql.length() - 1);
        _sql.append(")");
        PreparedStatement ps = c.prepareStatement(_sql.toString(),
                ResultSet.TYPE_SCROLL_INSENSITIVE,
                ResultSet.CONCUR_READ_ONLY);
        _dirtyCount = 0;
        ps.setString(++_dirtyCount, this.getID());
        ps.setString(++_dirtyCount, this.getModuleId());
        if (columnMap.get("desktopLocation") != null && !columnMap.get("desktopLocation").equals("")) {
            ps.setString(++_dirtyCount, this.getDesktopLocation());
        }
        ps.setString(++_dirtyCount, this.getPersonId());
        ps.setInt(++_dirtyCount, this.getHeight());
        ps.setInt(++_dirtyCount, this.getWidth());
        ps.setInt(++_dirtyCount, this.getX());
        ps.setInt(++_dirtyCount, this.getY());
        ps.executeUpdate();
        ps.close();
    }


    private String getString(ResultSet rs, Object column) {
        if (column != null && !column.toString().equals("")) {
            try {
                return rs.getString(((ColumnMapping) column).getColumnAlias());
            } catch (SQLException ex) {
                return null;
            }
        }
        return null;
    }

    private Integer getInt(ResultSet rs, Object column) {
        if (column != null && !column.toString().equals("")) {
            try {
                return rs.getInt(((ColumnMapping) column).getColumnAlias());
            } catch (SQLException ex) {
                return null;
            }
        }
        return 0;
    }

    public DbModuleProperty clone() {
        DbModuleProperty moduleProperty = new DbModuleProperty(this.configCode);
        moduleProperty.setHeight(height);
        moduleProperty.setID(ID);
        moduleProperty.setModuleId(moduleId);
        moduleProperty.setWidth(width);
        moduleProperty.setPersonId(personId);
        moduleProperty.setDesktopLocation(desktopLocation);
        moduleProperty.setX(x);
        moduleProperty.setY(y);
        return moduleProperty;
    }


    public String getDesktopLocation() {
        return desktopLocation;
    }

    public void setDesktopLocation(String desktopLocation) {
        this.desktopLocation = desktopLocation;
    }
}
